package com.x2.modular.system.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.x2.base.pojo.node.ZTreeNode;
import com.x2.base.pojo.page.LayuiPageFactory;
import com.x2.base.pojo.page.LayuiPageInfo;
import com.x2.core.constant.Const;
import com.x2.core.constant.SysTreeNode;
import com.x2.core.util.ToolUtil;
import com.x2.modular.system.entity.Dept;
import com.x2.modular.system.entity.User;
import com.x2.modular.system.entity.UserRole;
import com.x2.modular.system.mapper.UserRoleMapper;
import com.x2.modular.system.model.params.UserRoleParam;
import com.x2.modular.system.model.result.UserRoleResult;
import com.x2.modular.system.service.DeptService;
import com.x2.modular.system.service.RoleService;
import com.x2.modular.system.service.UserRoleService;
import com.x2.modular.system.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * 用户和角色关联表 服务实现类
 *
 * @author liuhq
 * @since 2019-07-02
 */
@Service
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService {

    @Resource
    private UserService userService;
    @Resource
    private RoleService roleService;

    @Autowired
    private DeptService deptService;

    @Override
    public void add(UserRoleParam param) {
        UserRole entity = getEntity(param);
        this.save(entity);
    }

    @Override
    public void delete(UserRoleParam param) {
        this.removeById(getKey(param));
    }

    @Override
    public void update(UserRoleParam param) {
        UserRole oldEntity = getOldEntity(param);
        UserRole newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
    }

    @Override
    public UserRoleResult findBySpec(UserRoleParam param) {
        return null;
    }

    @Override
    public List<UserRoleResult> findListBySpec(UserRoleParam param) {
        return null;
    }

    @Override
    public LayuiPageInfo findPageBySpec(UserRoleParam param) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageList(pageContext, param);
        return LayuiPageFactory.createPageInfo(page);
    }

    private Serializable getKey(UserRoleParam param) {
        return param.getRelationId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private UserRole getOldEntity(UserRoleParam param) {
        return this.getById(getKey(param));
    }

    private UserRole getEntity(UserRoleParam param) {
        UserRole entity = new UserRole();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public void setUserRoleAuthority(Long roleId, String ids) {
        // 删除该角色所有用户
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.eq("role_id", roleId);
        this.remove(userRoleQueryWrapper);
        UserRole userRole;
        List<UserRole> userRoleList = new ArrayList<>();
        for (Long id : Convert.toLongArray(ids.split(","))) {
            if (id != null) {
                userRole = new UserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(id);
                userRoleList.add(userRole);
            }
        }
        this.saveBatch(userRoleList);
        // 刷新当前用户的权限
        userService.refreshCurrentUser();
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public void setRoleUserAuthority(Long userId, String roleIds) {
        //移除全部指定用户的全部角色
        User user = this.userService.getById(userId);
        if (user == null) {
            return;
        }
        // 删除该角色所有用户
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.eq("role_id", userId);
        this.remove(userRoleQueryWrapper);
        UserRole userRole;
        List<UserRole> userRoleList = new ArrayList<>();
        for (Long id : Convert.toLongArray(roleIds.split(","))) {
            userRole = new UserRole();
            userRole.setRoleId(id);
            userRole.setUserId(userId);
            userRoleList.add(userRole);
        }
        this.saveBatch(userRoleList);
        // 刷新当前用户的权限
        userService.refreshCurrentUser();
    }

    @Override
    public List<SysTreeNode> getSelectTreeData(Long roleId) {
        List<SysTreeNode> userTree = new ArrayList<>();
        QueryWrapper<Dept> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.select("dept_id deptId", "pid pid", "simple_name simpleName", "full_name fullName", "sort sort");
        deptQueryWrapper.orderByAsc("sort");
        List<Dept> deptList = deptService.list(deptQueryWrapper);
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.select("user_id userId");
        userRoleQueryWrapper.eq("role_id", roleId);
        Function<Object, String> mapper = e -> String.valueOf(e);
        List<String> userList = this.listObjs(userRoleQueryWrapper, mapper);
        List<SysTreeNode> tmpUserList;
        for (Dept dept : deptList) {
            userTree.add(SysTreeNode.changeDeptNode(dept, "optgroup"));
            tmpUserList = this.userService.getUserTree(dept.getDeptId());
            if (tmpUserList.size() > 0) {
                for (SysTreeNode userNode : tmpUserList) {
                    if (userList.contains(userNode.getId())) {
                        userNode.setSelected("true");
                    }
                    if (Const.ADMIN_ID.equals(Long.valueOf(userNode.getId()))) {
                        userNode.setDisabled("true");
                    }
                    userTree.add(userNode);
                }
            }
        }
        return userTree;
    }

    @Override
    public List<SysTreeNode> getSelectTreeDataAllowLogin(Long roleId) {
        List<SysTreeNode> userTree = new ArrayList<>();
        QueryWrapper<Dept> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.select("dept_id deptId", "pid pid", "simple_name simpleName", "full_name fullName", "sort sort");
        deptQueryWrapper.orderByAsc("sort");
        List<Dept> deptList = deptService.list(deptQueryWrapper);
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.select("user_id userId");
        userRoleQueryWrapper.eq("role_id", roleId);
        Function<Object, String> mapper = e -> String.valueOf(e);
        List<String> userList = this.listObjs(userRoleQueryWrapper, mapper);
        List<SysTreeNode> tmpUserList;
        for (Dept dept : deptList) {
            tmpUserList = this.userService.getUserTreeAllowLogin(dept.getDeptId());
            if (tmpUserList.size() > 0) {
                userTree.add(SysTreeNode.changeDeptNode(dept, "optgroup"));
                for (SysTreeNode userNode : tmpUserList) {
                    if (userList.contains(userNode.getId())) {
                        userNode.setSelected("true");
                    }
                    if (Const.ADMIN_ID.equals(Long.valueOf(userNode.getId()))) {
                        userNode.setDisabled("true");
                    }
                    userTree.add(userNode);
                }
            }
        }
        return userTree;
    }

    @Override
    public List<Long> getRoleList(Long userId) {
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.select("role_id roleId");
        if (ToolUtil.isNotEmpty(userId)) {
            userRoleQueryWrapper.eq("user_id", userId);
        }
        Function<Object, Long> mapper = e -> Long.valueOf(String.valueOf(e));
        List<Long> roleList = this.listObjs(userRoleQueryWrapper, mapper);
        return roleList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public void deleteByRoleId(Long roleId) {
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        if (ToolUtil.isNotEmpty(roleId)) {
            userRoleQueryWrapper.eq("role_id", roleId);
            this.remove(userRoleQueryWrapper);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60)
    public void deleteByUserId(Long userId) {
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        if (ToolUtil.isNotEmpty(userId)) {
            userRoleQueryWrapper.eq("user_id", userId);
            this.remove(userRoleQueryWrapper);
        }
    }

    @Override
    public List<ZTreeNode> roleZTreeListByUserId(Long userId) {
        List<Long> roleList = this.getRoleList(userId);
        if (roleList == null || roleList.size() == 0) {
            return this.roleService.roleTreeList();
        } else {
            Long[] longArray = Convert.toLongArray(roleList);
            return this.roleService.roleTreeListByRoleId(longArray);
        }
    }
}
